Valid number

Time: O(N); Space: O(1); hard

Validate if a given string can be interpreted as a decimal number.

Examples:

Input: s = “0”; Output: True

Input: s = ” 0.1 “; Output: True

Input: s = “abc”; Output: False

Input: s = “1 a”; Output: False

Input: s = “2e10”; Output: True

Input: s = ” -90e3 “; Output: True

Input: s = ” 1e”; Output: False

Input: s = “e3”; Output: False

Input: s = ” 6e-1”; Output: True

Input: s = ” 99e2.5 “; Output: False

Input: s = “53.5e93”; Output: True

Input: s = ” –6 “; Output: False

Input: s = “-+3”; Output: False

Input: s = “95a54e53”; Output: False

Notes:

  • It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number:

    • Numbers 0-9

    • Exponent - “e”

    • Positive/negative sign - “+”/“-”

    • Decimal point - “.”

Of course, the context of these characters also matters in the input.

[2]:
class InputType(object):
    INVALID = 0
    SPACE = 1
    SIGN = 2
    DIGIT = 3
    DOT = 4
    EXPONENT = 5

class Solution1(object):
    def isNumber(self, s) -> bool:
        """
        :type s: str
        :rtype: bool
        """

        transition_table = [[-1,  0,  3,  1,  2, -1],     # next states for state 0
                            [-1,  8, -1,  1,  4,  5],     # next states for state 1
                            [-1, -1, -1,  4, -1, -1],     # next states for state 2
                            [-1, -1, -1,  1,  2, -1],     # next states for state 3
                            [-1,  8, -1,  4, -1,  5],     # next states for state 4
                            [-1, -1,  6,  7, -1, -1],     # next states for state 5
                            [-1, -1, -1,  7, -1, -1],     # next states for state 6
                            [-1,  8, -1,  7, -1, -1],     # next states for state 7
                            [-1,  8, -1, -1, -1, -1]]     # next states for state 8

        state = 0
        for char in s:
            inputType = InputType.INVALID
            if char.isspace():
                inputType = InputType.SPACE;
            elif char == '+' or char == '-':
                inputType = InputType.SIGN
            elif char.isdigit():
                inputType = InputType.DIGIT
            elif char == '.':
                inputType = InputType.DOT
            elif char == 'e' or char == 'E':
                inputType = InputType.EXPONENT;

            state = transition_table[state][inputType];

            if state == -1:
                return False;

        return state == 1 or state == 4 or state == 7 or state == 8
[4]:
sol = Solution1()
s = " 0.1 "
assert sol.isNumber(s) == True
s = "abc"
assert sol.isNumber(s) == False
s = "1 a"
assert sol.isNumber(s) == False
s = "2e10"
assert sol.isNumber(s) == True
s = " -90e3 "
assert sol.isNumber(s) == True
s = " 1e"
assert sol.isNumber(s) == False
s = "e3"
assert sol.isNumber(s) == False
s = " 6e-1"
assert sol.isNumber(s) == True
s = " 99e2.5 "
assert sol.isNumber(s) == False
s = "53.5e93"
assert sol.isNumber(s) == True
s = " --6 "
assert sol.isNumber(s) == False
s = "-+3"
assert sol.isNumber(s) == False
s = "95a54e53"
assert sol.isNumber(s) == False
[5]:
class Solution2(object):
    def isNumber(self, s) -> bool:
        """
        :type s: str
        :rtype: bool

        """
        import re
        return bool(re.match("^\s*[\+-]?((\d+(\.\d*)?)|\.\d+)([eE][\+-]?\d+)?\s*$", s))
[6]:
s = Solution2()
s = " 0.1 "
assert sol.isNumber(s) == True
s = "abc"
assert sol.isNumber(s) == False
s = "1 a"
assert sol.isNumber(s) == False
s = "2e10"
assert sol.isNumber(s) == True
s = " -90e3 "
assert sol.isNumber(s) == True
s = " 1e"
assert sol.isNumber(s) == False
s = "e3"
assert sol.isNumber(s) == False
s = " 6e-1"
assert sol.isNumber(s) == True
s = " 99e2.5 "
assert sol.isNumber(s) == False
s = "53.5e93"
assert sol.isNumber(s) == True
s = " --6 "
assert sol.isNumber(s) == False
s = "-+3"
assert sol.isNumber(s) == False
s = "95a54e53"
assert sol.isNumber(s) == False